package com.weifei.core.ioc;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

public class WFBeanDefinitionReader {

    private List<String> registryBeanClass = new Vector<>();
    private Properties config = new Properties();
    private final String SCAN_PACKAGE = "scanPackage";

    public WFBeanDefinitionReader() {}
    public WFBeanDefinitionReader(String... locations) {
        Arrays.stream(locations).forEach( location -> {
            this.doLoadConfig(location);
        });
        this.doScanner(config.getProperty("scanPackage"));
    }
    private void doLoadConfig(String location) {
        InputStream input = null;
        // 可能有多个配置文件，需要修改逻辑
        String configPath = location.replace("classpath", "")
                .replace(":", "").replaceAll(" ", "");
        input = this.getClass()
                .getClassLoader()
                .getResourceAsStream(configPath);
        try {
            config.load(input);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 扫描路径下的注解，生产ioc容器
     * @param scanPath
     */
    private void doScanner(String scanPath) {
        URL url = this.getClass()
                .getClassLoader()
                .getResource("/"
                        + scanPath.replaceAll("\\.", "/"));
        File classDir = new File(url.getFile());
        for (File file : classDir.listFiles()) {
            if (file.isDirectory()) {
                doScanner(scanPath + "." + file.getName());
            }else {
                if (!file.getName().endsWith(".class")){
                    continue;
                }
                String clazzName = scanPath + "."
                        + file.getName().replace(".class", "");
                registryBeanClass.add(clazzName);
            }
        }
    }

    public Properties getConfig() {
        return this.config;
    }

    public List<WFBeanDefinition> loadBeanDefinition() throws ClassNotFoundException {
        List<WFBeanDefinition> result = new ArrayList<>();

        for (String className : registryBeanClass) {
            Class<?> clazz = Class.forName(className);
            if (clazz.isInterface()) {
                continue;
            }
            result.add(doCreateBeanDefinition(
                    this.toLowerFirstCase(clazz.getSimpleName()),
                    clazz.getName()
            ));
            Class<?>[] interfaces = clazz.getInterfaces();
            for (Class<?> c : interfaces) {
                result.add(doCreateBeanDefinition(
                        c.getName(),
                        clazz.getName()
                ));
            }
        }
        return result;
    }

    private WFBeanDefinition doCreateBeanDefinition(String factoryBeanName, String beanClassName){
        WFBeanDefinition beanDefinition = new WFBeanDefinition();
        beanDefinition.setFactoryBeanName(factoryBeanName);
        beanDefinition.setBeanClassName(beanClassName);
        return beanDefinition;
    }
    private String toLowerFirstCase(String simpleName) {
        char[] chars = simpleName.toCharArray();
        if (chars[0]>=65 && chars[0] <=90) {
            chars[0] += 32;
        }
        return String.valueOf(chars);
    }
}
